home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / MENU_UTL / TPPDMENU / TPPDMENU.DOC < prev    next >
Text File  |  1990-01-11  |  20KB  |  482 lines

  1. TPPDMENU.PAS                        11:38:21 PM  Jan 11, 1990
  2.  
  3. Pull down menus for Turbo Pascal Applications
  4.  
  5. Copyright August 1989, January 1990 -- Ken Henderson
  6.  
  7. Lots of libraries and routines have been developed in order to
  8. give the pascal programmer the sleekness of pull down menus in
  9. his applications.  This is no exception.  This one differs in
  10. that no code is generated, the menus are file based and as such
  11. are very flexible.  You can keep the menu data in binary .MNU
  12. files, you can build it into your applications -- whatever you
  13. want.  The actual invocation of the menus only requires one line
  14. of code and is the same regardless of the contents of the menus.
  15. Based in part on the editor toolbox menus and requiring the Turbo
  16. Professional library of routines from TurboPower Software, these
  17. menus offer unmatched flexibility and speed. The process, simply
  18. put, is:  you create a menu data file, compile it with the
  19. supplied menu compiler, and reference it from within your
  20. application -- that's all there is to it -- and there you have it
  21. -- pull down menus that are both flexible and incredibly fast.
  22.  
  23. The question arises: "If I have Turbo Professional, why would I
  24. need your pull down menus unit?  TPMENU suits me just fine."
  25. Well, you indeed might not need this unit if you have Turbo
  26. Professional and TPMENU.  I use this unit because a) I can change
  27. the menus without recompiling the code that uses them  b) I like
  28. to distribute the menu source and compiler with my applications
  29. so that my users can modify the menus if they like (to change the
  30. trigger keys, etc.) and c) because these menus only require two
  31. calls to initialize and invoke the menus.  I love the Turbo
  32. Professional stuff and you might not need this unit.  If you
  33. think you might, read on.
  34.  
  35. The first step in using TPPDMENU is to build the menu data file
  36. on which the menus are based.  This is simple and will be covered
  37. later.  The second step is to call the initialization routine
  38. from within your program.  It has the form:
  39.  
  40.   Function InitMenus(MenuName : String; ColorTable : MenuAttributeArray;
  41.                        UserDefinedHelpPtr,
  42.                        UserDefinedValidationPtr,
  43.                        UserDefinedEvaluatePtr,
  44.                        UserDefinedExitMenusPtr,
  45.                        BuiltInMenuAddress : Pointer) : Integer;
  46.  
  47. Menuname is the name of the file containing the menu data, pass
  48. an empty string if you are using built-in data (covered below).
  49. Calling InitMenus with the name of a menu file would go something
  50. like this:
  51.  
  52.            InitMenus('MYMENUS.MNU',MenuColors,nil,nil,nil,nil,nil);
  53.  
  54. ColorTable is the table of colors to be used by TPPDMENU when
  55. displaying the menus.  You will probably want to have two such
  56. tables, one for color and the other for mono, and send one of
  57. them to TPPDMENU based on the current display mode.  The
  58. ColorTable is of type MenuAttributeArray and has the following
  59. form:
  60.  
  61.    TextColor,                     {Normal menu color}
  62.    FrameColor,                    {Menu frame color}
  63.    SelectColor,                   {Selected menu item color}
  64.    HighLightColor                 {Highlighted selection character in menu}
  65.  
  66.    MenuAttributeArray = array[ColorType] of Byte;
  67.  
  68. UserDefindedHelpPtr is used to pass the address of a routine to
  69. be invoked when F1 is pressed.  If you aren't using this feature
  70. pass nil in its place.  It is a generic pointer type which is
  71. "absoluted" to a global variable of UserHelpType and should be of
  72. the form:
  73.  
  74. {$F+}
  75. Procedure(OptionIndex : Integer);
  76. {$F-}
  77.  
  78. UserDefinedValidationPtr is used to pass the address of a routine
  79. to validate a user's access to a particular menu option.  Using
  80. this routine, you can allow access to some routines, while not
  81. allowing others.  For instance, you might not want to give the
  82. user access to the Edit option until he has selected the Open
  83. option.  Routines that are accessible will have their trigger
  84. keys (usually the first key) highlighted and will allow the user
  85. to move the selection bar to them.  Routines that are not
  86. accessible will not have their trigger key highlighted, nor will
  87. the user be able to move the selection key to them.  If you are
  88. not using this option pass a nil value to it.  It is a generic
  89. pointer type which is "absoluted" to a global variable of
  90. UserValidationType and should be of the form:
  91.  
  92. {$F+}
  93. Function(OptionIndex : Integer) : boolean;
  94. {$F-}
  95.  
  96. UserDefinedEvaluatePtr is used to evaluate a given menu item's
  97. status.  You may have an option that is, say, a toggle.  Its
  98. status is associated with a particular boolean variable.  You
  99. could use this routine to either display ON or OFF beside the
  100. text of the menu item in order to show its status.  If you are
  101. not using this option, pass a nil in its place.  It is a generic
  102. pointer type which is "absoluted" to a global variable of
  103. UserEvaluateType and should be of the form:
  104.  
  105. {$F+}
  106. Procedure(C : Integer; Stat : Byte; var S : String);
  107. {$F-}
  108.  
  109. UserDefinedExitMenusPtr is used to determine which options
  110. selected actually cause the menu system to be exited and which
  111. ones keep the menu system on the screen.  Often the only option
  112. which should have the menus exited is the Quit or Exit option
  113. itself, depending on your application.  If you are building an
  114. editor, and you have an option that turns block marking on such
  115. that moving the cursor marks the block, of course you would exit,
  116. so the user could move the cursor in your editor.  If you do not
  117. intend to use this option, pass a nil value in its place.  It is
  118. a generic pointer type which is "absoluted" to a global variable
  119. of UserValidationType and should be of the form:
  120.  
  121. {$F+}
  122. Function(OptionIndex : Integer) : boolean;
  123. {$F-}
  124.  
  125. BuiltInMenuAddress is used to point to the area of memory where
  126. the menu data is located.  This option is exclusive of the
  127. Menuname option.  If you pass the Menuname option, you may not
  128. pass this one (it will have no effect) and if you pass this
  129. option you should pass an empty string for the Menuname.
  130. Essentially, this option's primary use is to bind the menu data
  131. file into your .EXE.  The process is as follows: first create and
  132. compile the menu data file as you would normally.  You may want
  133. to test the menu data file's contents while it is file-based and,
  134. once it is satisfactory, bind it to your .EXE.  Secondly, use
  135. Borland's BINOBJ utility to create an .OBJ that can be linked
  136. into your code using the $L directive.  The command line for
  137. BINOBJ would be something like:
  138.  
  139.                     BINOBJ MDATA.MNU MDATA MYMENUS
  140.  
  141. MDATA.MNU is the name of the binary file to convert, MDATA is the
  142. name of the .OBJ to create and MYMENUS is the name of the dummy
  143. identifier that you may reference by address for TPPDMENU's
  144. purposes.  You could then call InitMenus with the following
  145. parms:
  146.            InitMenus('',MenuColors,nil,nil,nil,nil,@MYMENUS);
  147.  
  148. The PUBLIC identifier, MYMENUS, created by BINOBJ, just gives us
  149. something with which to reference the area of memory containing
  150. the menu data.
  151.  
  152. A conditional define, called AllowHotKeys, allows you to have
  153. keys which begin with a null (most special keys, such as the
  154. function keys, and the Alt and Ctrl key combinations) to
  155. essentially exit from the menu system to be processed by your
  156. application.  For instance, you could set up Alt-X to exit the
  157. application.  When  Alt-X was pressed (with AllowHotKeys defined)
  158. the menus would exit and would insert the key sequence for Alt-X
  159. into the keyboard buffer.  Your application could then read the
  160. keyboard and determine that the user wanted to exit and then do
  161. so.
  162.  
  163. Be sure to declare any of the procedure or function addresses you pass to
  164. TPPDMENU as far using the $F+ compiler directive.
  165.  
  166. Here is a simple program which uses TPPDMENU:
  167.  
  168. {===============================================================}
  169.  
  170. {
  171.                               TESTMENU.PAS
  172. }
  173.  
  174. program Test;
  175.   {-Test pulldown menus}
  176.  
  177. uses
  178.   TpCrt,                     {screen routines - standard unit}
  179.   Dos,                       {dos calls - standard unit}
  180.   TpString,                  {string handling}
  181.   TpPdmenu;                  {pulldown menu interface}
  182.  
  183.   var
  184.    choice : integer;
  185.    exitm : boolean;
  186.    Ch : char;
  187.    Attribs : MenuAttributeArray;    {Currently selected attributes}
  188.  
  189. const
  190.   MonoAttr : MenuAttributeArray = {For mono systems}
  191.   (
  192.    $07,                           {TextColor}
  193.    $0F,                           {FrameColor}
  194.    $70,                           {SelectColor}
  195.    $0F                            {HighLightColor}
  196.    );
  197.  
  198.   ColorAttr : MenuAttributeArray = {For color systems}
  199.   (
  200.    $70,                           {TextColor}
  201.    $78,                           {FrameColor}
  202.    $0F,                           {SelectColor}
  203.    $74                            {HighLightColor}
  204.    );
  205.  
  206. begin                        {Test menus}
  207.  
  208.   {-Initialize some variables}
  209.   choice := 0;
  210.   exitm := false;   {-Is passed thru GetMenuChoice; must be set to True if
  211.                       Hot keys are to be processed properly}
  212.  
  213.   {-Set up color table}
  214.   case CurrentMode of
  215.     2, 7 :
  216.    Attribs:=MonoAttr;
  217.   else
  218.    Attribs:=ColorAttr;
  219.   end;
  220.  
  221.   {-Initialize menu system with color set Attribs, no user help, no user
  222.     validation, no user special variable evaluation and no exit check}
  223.  
  224.   if InitMenus('TEST.MNU',Attribs,nil,nil,nil,nil,nil) = 0 then
  225.   GetMenuChoice(choice,exitm);
  226.  
  227.   {-Show the choice}
  228.  
  229.   clrscr;
  230.   Writeln(choice);
  231.   ch:=readkey;
  232. end.                         {Test menus}
  233.  
  234. {===============================================================}
  235.  
  236. Note that InitMenus returns a numeric value; if the value is
  237. non-zero an error of some sort has occured.  The posible return
  238. values are:
  239.  
  240. Value          Meaning
  241. -1             Insufficient memory
  242. -2             Root menu is not first in the menu data
  243. -3             Too many submenus have been specified
  244. -4             Level number is out of synch in menu data
  245. -5             Error opening the menu data file
  246. -6             Error reading the menu data file
  247.  
  248. Below is a sample menu data file.  It appears a little confusing
  249. at first, but is actually very simple.
  250.  
  251. {===============================================================}
  252.  
  253. *
  254. *       TEST.MSC
  255. *       MENU SOURCE FILE
  256. *       COMPILE WITH MAKEPMNU
  257. *
  258. *
  259. *
  260. *
  261.  
  262. ************************ Main menu
  263. *menulev, xposn, yposn, xsize, ysize, submax
  264. 1,   5,   4,  40,   1,   2
  265. ************************ Main menu selections
  266. *command, dispoffset, special, selectoffset, string
  267. 255,      2,   0,   0,   'Install'
  268. 255,     11,   0,   0,   'Quit'
  269. ************************ Install menu
  270. 2,   6,   6,  23,   4,  4
  271. 255,    0,   0,   0,  'Keyboard'
  272. 1,      1,   0,   0,  'Switches'
  273. 2,      2,   0,   0,  'Colors'
  274. 255,    3,   0,   0,  'Macros...'
  275. ************************ Keyboard menu
  276. 3,   19,    8,  20,  2,  2
  277. 3,      0,   3,   0,  'Read'
  278. 4,      1,   0,   0,  'Edit'
  279. ************************ Switches menu (none, required as placeholder)
  280. 3,   1,   8,  10,   0,  0
  281. ************************ Colors menu (none, required as placeholder)
  282. 3,   1,   8,  10,   0,  0
  283. ************************ Macros menu
  284. 3,   19,   10,  20,  3,  3
  285. 5,      0,   3,   0,  'Read'
  286. 6,      1,   0,   0,  'Edit'
  287. 7,      2,   0,   0,  'Delete'
  288. ************************ Quit "menu"
  289. 2,  13,   6,  10,   1,   1
  290. 50,      0,   0,   0,   'Quit'
  291. 255
  292.  
  293.  
  294. menulevel                                     ─────┐
  295. │   xposition                                      │
  296. │   │       yposition                              │
  297. │   │       │   menuwidth                          ├─Header
  298. │   │       │   │    menudepth                     │
  299. │   │       │   │    │    maximum items            │
  300. │   │       │   │    │    │                        │
  301. 2,  6,      6,  23,  4,   4                   ─────┘
  302.  
  303. 255,      0,   0,   0,  'Keyboard'            ─────┐
  304. 1,        1,   0,   0,  'Switches'                 │
  305. 2,        2,   0,   0,  'Colors'                   │
  306. 255,      3,   0,   0,  'Macros...'                │
  307. │         │    │    │    │                         │
  308. │         │    │    │    itemtext                  ├─Body
  309. │         │    │    │                              │
  310. │         │    │    trigger offset                 │
  311. │         │    variabletype                        │
  312. │         itemnumber                               │
  313. │                                                  │
  314. commandorder                                  ─────┘
  315.  
  316. Menu level : the level of the current menu.  Levels start at 0 and can be
  317. as high as 3.  Each submenu is one level greater than its parent menu level.
  318.  
  319. HEADER:
  320. Xposition          : the horizontal position of this menu
  321.  
  322. Yposition          : the vertical position of this menu
  323.  
  324. Menuwidth          : the horizontal width of this menu
  325.  
  326. Menudepth          : the vertical depth of this menu
  327.  
  328. Maxitems           : the number of items on this menu
  329.  
  330. BODY:
  331. Commandorder       : the command number of the associate command or function.
  332.  
  333. Itemnumber         : this menu option's order among the other menu options.
  334.  
  335. Variabletype       : the type of the variable you wish to display next to this
  336.                      option -- 0 for none, 1 for boolean (logical), 2 for
  337.                      numeric and 3 for string. TPPDMENU passes this value to
  338.                      your evaluator routine so that you may display a variables
  339.                      value along side it on the menus.  Leave the value set to
  340.                      0 if you do not intend to display a value beside this menu
  341.                      option.
  342.  
  343. Triggeroffset      : is the offset, less one, where the trigger is located in
  344.                      the Itemtext.  In other words, if this option is set to
  345.                      0, the trigger key is the first letter of the Itemtext
  346.                      and so on
  347.  
  348. Itemtext           : the actual text that composes a menu item.  The first
  349.                      character of a menu item is normally it's "trigger key" --
  350.                      the key that causes it to be executed, no matter where you
  351.                      happen to be in its particular menu.
  352.  
  353.  
  354. Note items which have submenus to them are listed as Commandord 255.  Also
  355. note that the list ends with a lone 255, this is the EOM, or End of Menu
  356. marker.  Since there is no way to tie a particular submenu to a menu option,
  357. it is done sequentially, that is, the first submenu following a menu is
  358. associated with menu item 0, the second with menu item 1 and so on.
  359. Therefore, if you wish to have options on the same menu which reference
  360. submenus and others which do not, you will have to set up place holder or
  361. filler menus.  These are simply menus associated with a particular menu item
  362. that does not actually have a submenu associated with it, but precedes one
  363. that does.  A filler menu need only be one line long and does actually contain
  364. any menu items.  The Switches and Colors submenus above are examples of such
  365. menus.  They do not actually represent submenus themselves, but are necessary
  366. because we wish to place the Keyboard and Macro submenu options on opposite
  367. ends of their parent menu, Install.
  368.  
  369.  
  370. {===============================================================}
  371.  
  372. Compiling with MAKEPMNU
  373.  
  374. TPPDMENU menu files are compiled with a supplied utility MAKEPMNU.  You may
  375. distribute MAKEPMNU with your applications, if you like, so that your users
  376. may customize their menus.
  377.  
  378. Using MAKEPMNU is easy, just pass it the name of the menu file to compile.
  379. The menu source file extension defaults to .MSC and the menu object file
  380. extension defaults to .MNU.  Even with the biggest menu source
  381. files, the compile should complete in a second or two.
  382.  
  383.                MAKEPMNU test
  384.  
  385. {===============================================================}
  386.  
  387. Here are a few routines to serve as examples of those you might
  388. pass to InitMenus:
  389.  
  390. {Here is one to be passed as an evaluator -- a routine to display
  391. text along side a menu option}
  392. {$F+}
  393. procedure EvaluateMenuOpt(C : Integer; Stat : Byte; var S : String);
  394. var
  395.  Ss : string;
  396. begin
  397.   Ss := '';
  398.   case stat of    {-status of three indicates a string}
  399.   3 : begin
  400.       case C of
  401.       3 : Ss := JustFileName(kbdin);    {-Display the name of the keyboard
  402.                                           file that was read}
  403.       5 : Ss := JustFileName(MacroInFile);  {-Display the name of the macro
  404.                                               file that was read}
  405.       end;
  406.       end;
  407.   end;
  408.   Move(Ss[1], S[Length(S)-Length(Ss)], Length(Ss));
  409. end;
  410.  
  411. {Here is one to serve as a menu exit function -- it determines
  412. whether the menus should be erased when a choice is made, or
  413. whether they should be left active}
  414.  
  415. Function AllowExit(C : Integer): Boolean;
  416. begin
  417.   AllowExit := false;
  418.   If C=50 then AllowExit:=True;  {Only the Quit option exits the menus}
  419. end;
  420.  
  421. {This routine determines whether a specific item is accesible
  422. based on whether a variable has been initialized with a value yet}
  423.  
  424. Function AllowAccess(AccessIndex : Integer) : boolean;
  425. begin
  426.   AllowAccess:=True;
  427.   case AccessIndex of
  428.   6,7 : if MacroInFile = '' then AllowAccess:=false;
  429.       {-Don't allow Editing or Deleting of macros unless some have been
  430.         loaded}
  431.   end;
  432. end;
  433.  
  434. {===============================================================}
  435.  
  436. ToggleBooleanVal(var InBoolean : boolean);
  437.  
  438. ToggleBooleanVal allows you to force a toggle option to either ON
  439. or OFF.  When Space or BackSpace is pressed while in the menus
  440. the global variable, ToggleBoolean, will be set to either 1,
  441. when Backspace is pressed, to force it to OFF, or 2, when Space
  442. is pressed, to force it to ON.  The menus will then behave as
  443. though Enter were pressed and your application should use
  444. ToggleBooleanVal to toggle the boolean variable appropriately.
  445. This would allow you to force a toggle to a particular value
  446. without knowing its prior state, a feature handy in keyboard
  447. macros.  You can use ToggleBooleanVal to toggle the value whether
  448. Space or Backspace or just the Enter key was pressed.  If Space
  449. or Backspace where not pressed (and, consequently
  450. ToggleBoolean=0) the routine will simply toggle the value passed
  451. to it.
  452.  
  453. {===============================================================}
  454.  
  455. >>>>>FEATURES NEW TO THIS RELEASE OF TPPDMENU
  456.  
  457. I have added mouse support with this release of TpPdMenu via the
  458. TpPdMous unit.  This unit requires TpMouse from TurboPower Software
  459. and would actually add mouse support to any program, since it simply
  460. translates mouse movements or pressed buttons into keys and pokes
  461. them into the keyboard buffer via TpCrt.StuffKey.  Currently, the
  462. left button is the equivalent of pressing <Enter>, the right button
  463. is the equivalent of pressing <Esc> and pressing both buttons is the
  464. equivalent of pressing <F1>.  You may set both the speed and the
  465. default button-to-key translations by modifying TpPdMous.
  466.  
  467. That's about all there is to TPPDMENU.  The source is provided to
  468. both the unit and the compiler, keep in mind that you will need
  469. Turbo Professional from TurboPower Software in order to use
  470. TPPDMENU. You may extract the sample program and sample menu data
  471. file here if you wish for testing the unit.
  472.  
  473. This unit is distributed as "freeware" and you are under no
  474. obligation to me for using it.  I only ask that you leave my
  475. copyright notices in tact and that if you redistribute this
  476. software (either by electronic or other means) you keep the
  477. files here together and do not omit any of them.
  478.  
  479. Happy menuing!
  480.  
  481. Ken Henderson
  482.